<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="1038.32">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; color: #376c2a}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; min-height: 22.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000; min-height: 12.0px}
p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #cd1713}
p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000}
p.p10 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
p.p11 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #ad140d}
p.p12 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #606060}
span.s1 {color: #001bb9}
span.s2 {color: #102ac3}
span.s3 {color: #737373}
span.s4 {color: #008225}
span.s5 {color: #000000}
span.s6 {color: #606060}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1">//Copyright (C) 2006<span class="Apple-converted-space">  </span>Nick Collins, conversion from work by Phil McLeod</p>
<p class="p1">//distributed under the terms of the GNU General Public License<span class="Apple-converted-space"> </span></p>
<p class="p2"><br></p>
<p class="p3"><b>Tartini<span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>pitch tracker</b></p>
<p class="p4"><br></p>
<p class="p5"><b>#freq, hasFreq = Tartini.kr(in)</b></p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span></p>
<p class="p5">This alternative pitch follower uses autocorrelation like Pitch, but with an adapted method, and calculated via FFT. There are some parameters for you to choose the window size and other aspects of the calculation, but a user who doesn't want to worry too much about this kind of stuff, please just use the defaults and don't worry about them. <span class="Apple-converted-space"> </span></p>
<p class="p4"><br></p>
<p class="p5"><b>in</b>- the audio rate input signal</p>
<p class="p5"><b>threshold</b>- In autocorrelation function peak picking, chooses first peak within this threshold of the maximum peak. Leave it at 0.93 by default.<span class="Apple-converted-space"> </span></p>
<p class="p5"><b>n</b>- data window size (on OS X without fftw, only 2048, 1024 and 512 supported, and k must be n/2)</p>
<p class="p5"><b>k</b>- autocorrelation lags, actual FFT size will be n+k (this may lead to nonstandard non-power of 2 FFTs, fftw copes, don't worry about it...). It is recommended by Phil McLeod that you keep k at n/2 (if you set k=0 you will get that default) else at most 3*n/4.<span class="Apple-converted-space"> </span></p>
<p class="p5"><b>overlap</b>- overlap size in samples (ie, 1024 window, 256 overlap means advance by 768 samples each time)</p>
<p class="p5"><b>smallCutoff</b>- a parameter for determining when a peak is recorded in the autocorrelation function, advanced use only.<span class="Apple-converted-space">  </span>Suggest you never put this too low, ie near zero, because then every possible lag in the autocorrelation becomes a potential peak, CPU cost goes up, and results won't necessarily be any good.<span class="Apple-converted-space"> </span></p>
<p class="p4"><br></p>
<p class="p5">There are two outputs (see examples code below)</p>
<p class="p5"><b>freq</b>- fundamental frequency trail</p>
<p class="p5"><b>hasFreq</b>- confidence in the estimate- 0 = no fundamental found, 1= fully confident, then also values inbetween- will be above 0.9 if really finding a strong periodicity</p>
<p class="p4"><br></p>
<p class="p5">In technical terms, this UGen calculates a modified autocorrelation function following the method used in the Tartini open source (GNU GPL) pitch following software (http://miracle.otago.ac.nz/postgrads/tartini/)</p>
<p class="p4"><br></p>
<p class="p5">The algorithm is based on the following paper:</p>
<p class="p5">Philip McLeod and Geoff Wyvill (2005) A Smarter Way to Find Pitch. ICMC Proceedings; 138-141.</p>
<p class="p4"><span class="Apple-converted-space">         </span></p>
<p class="p5">Note: For the default and standard values of N and k (512 and 256, 1024 and 512, 2048 and 1024) initialisation time of the UGen at run-time should be fast (due to precalculation when the plug-in loads). BUT, for nonstandard choices, the first time you instantiate a UGen there will be a CPU spike. ADVANCED- hack the code in the load() function to choose your own standard precalculated FFT sizes for fftw.<span class="Apple-converted-space">     </span></p>
<p class="p4"><br></p>
<p class="p5"><b>Examples: (use headphones!)</b></p>
<p class="p4"><br></p>
<p class="p6">s = <span class="s1">Server</span>.local;</p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p8">//fast test of live pitch tracking, not careful with amplitude of input (see better example below)</p>
<p class="p9">{<span class="s2">Saw</span>.ar(<span class="s2">Tartini</span>.kr(<span class="s2">SoundIn</span>.ar)[0],0.2)}.play</p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p7"><br></p>
<p class="p9">(</p>
<p class="p9">a= <span class="s2">SynthDef</span>(<span class="s3">"testtartini"</span>,{<span class="s2">arg</span> infreq=440;</p>
<p class="p9"><span class="Apple-tab-span">	</span><span class="s2">var</span> in, freq, hasFreq, out;</p>
<p class="p7"><span class="Apple-tab-span">	</span></p>
<p class="p9"><span class="Apple-tab-span">	</span>in=<span class="s2">SinOsc</span>.ar(infreq);</p>
<p class="p7"><span class="Apple-tab-span">	</span></p>
<p class="p9"><span class="Apple-tab-span">	</span># freq, hasFreq = <span class="s2">Tartini</span>.kr(in);</p>
<p class="p7"><span class="Apple-tab-span">	</span></p>
<p class="p9"><span class="Apple-tab-span">	</span>freq.poll;<span class="Apple-converted-space"> </span></p>
<p class="p7"><span class="Apple-tab-span">	</span></p>
<p class="p9"><span class="Apple-tab-span">	</span><span class="s2">Out</span>.ar(0,[<span class="s2">SinOsc</span>.ar(freq,0.1),in]);</p>
<p class="p9">}).play(s);</p>
<p class="p9">)</p>
<p class="p7"><br></p>
<p class="p9">a.set(<span class="s4">\infreq</span>,301);</p>
<p class="p7"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p11"><span class="s5">c=</span><span class="s1">Buffer</span><span class="s5">.read(s,</span><span class="s6">"/Volumes/data/audio/nikkisitar/warmup.wav"</span><span class="s5">); </span>//sitar test file, try anything you have on your disk</p>
<p class="p10"><br></p>
<p class="p6">c.numFrames</p>
<p class="p10"><br></p>
<p class="p11"><span class="s5">( </span>//sample tracking</p>
<p class="p12"><span class="s1">SynthDef</span><span class="s5">(</span>"pitchFollow1"<span class="s5">,{</span></p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">var</span> in, amp, freq, hasFreq, out;</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span>in = <span class="s1">PlayBuf</span>.ar(1,c.bufnum, loop:1);</p>
<p class="p6"><span class="Apple-tab-span">	</span>amp = <span class="s1">Amplitude</span>.kr(in, 0.05, 0.05);</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span># freq, hasFreq = <span class="s1">Tartini</span>.kr(in);</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span>out = <span class="s1">Mix</span>.new(<span class="s1">VarSaw</span>.ar(freq * [0.5,1,2], 0, <span class="s1">LFNoise1</span>.kr(0.3,0.1,0.1), amp));</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">Out</span>.ar(0,[out,in])</p>
<p class="p6">}).play(s);</p>
<p class="p6">)</p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p11">//analogous to example in the Pitch helpfile<span class="Apple-converted-space"> </span></p>
<p class="p6">(</p>
<p class="p12"><span class="s1">SynthDef</span><span class="s5">(</span>"pitchFollow1"<span class="s5">,{</span></p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">var</span> in, amp, freq, hasFreq, out;</p>
<p class="p6"><span class="Apple-tab-span">	</span>in = <span class="s1">Mix</span>.new(<span class="s1">AudioIn</span>.ar([1,2]));</p>
<p class="p6"><span class="Apple-tab-span">	</span>amp = <span class="s1">Amplitude</span>.kr(in, 0.05, 0.05);</p>
<p class="p6"><span class="Apple-tab-span">	</span># freq, hasFreq = <span class="s1">Tartini</span>.kr(in, 0.93,1024,512,512);<span class="Apple-converted-space"> <span class="Apple-tab-span">	</span></span></p>
<p class="p11"><span class="s5"><span class="Apple-tab-span">	</span></span>//freq = Lag.kr(freq.cpsmidi.round(1).midicps, 0.05);</p>
<p class="p6"><span class="Apple-tab-span">	</span>out = <span class="s1">Mix</span>.new(<span class="s1">VarSaw</span>.ar(freq * [0.5,1,2], 0, <span class="s1">LFNoise1</span>.kr(0.3,0.1,0.1), amp));</p>
<p class="p6"><span class="Apple-tab-span">	</span>6.do({</p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>out = <span class="s1">AllpassN</span>.ar(out, 0.040, [0.040.rand,0.040.rand], 2)</p>
<p class="p6"><span class="Apple-tab-span">	</span>});</p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">Out</span>.ar(0,out)</p>
<p class="p6">}).play(s);</p>
<p class="p6">)</p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p4"><br></p>
<p class="p11">//testing weirder parameter settings (these are inconsistent, really a check on test code in plug-in)</p>
<p class="p11">//very inefficient overlap, very fast reacting FFT, Mouse control of both thresholds- will force errors in certain ranges (maybe this is a fun effect)</p>
<p class="p6">(</p>
<p class="p12"><span class="s1">SynthDef</span><span class="s5">(</span>"pitchFollow1"<span class="s5">,{</span></p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">var</span> in, amp, freq, hasFreq, out;</p>
<p class="p6"><span class="Apple-tab-span">	</span>in = <span class="s1">Mix</span>.new(<span class="s1">AudioIn</span>.ar([1,2]));</p>
<p class="p6"><span class="Apple-tab-span">	</span>amp = <span class="s1">Amplitude</span>.kr(in, 0.05, 0.05);</p>
<p class="p6"><span class="Apple-tab-span">	</span># freq, hasFreq = <span class="s1">Tartini</span>.kr(in, MouseX.kr(0.5,1),512,1024,768, MouseY.kr(0.25,0.75)); //fast reacting</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p11"><span class="s5"><span class="Apple-tab-span">	</span></span>//freq = Lag.kr(freq.cpsmidi.round(1).midicps, 0.05);</p>
<p class="p6"><span class="Apple-tab-span">	</span>out = <span class="s1">Mix</span>.new(<span class="s1">VarSaw</span>.ar(freq * [0.5,1,2], 0, <span class="s1">LFNoise1</span>.kr(0.3,0.1,0.1), amp));</p>
<p class="p6"><span class="Apple-tab-span">	</span>6.do({</p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>out = <span class="s1">AllpassN</span>.ar(out, 0.040, [0.040.rand,0.040.rand], 2)</p>
<p class="p6"><span class="Apple-tab-span">	</span>});</p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">Out</span>.ar(0,out)</p>
<p class="p6">}).play(s);</p>
<p class="p6">)</p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p11">//check hasFreq values<span class="Apple-converted-space"> </span></p>
<p class="p6">(</p>
<p class="p12"><span class="s5">a= </span><span class="s1">SynthDef</span><span class="s5">(</span>"testtartini"<span class="s5">,{</span></p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">var</span> in, freq, hasFreq, out;</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span>in=<span class="s1">AudioIn</span>.ar(1);</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span># freq, hasFreq = <span class="s1">Tartini</span>.kr(in);</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span>hasFreq.poll;</p>
<p class="p10"><span class="Apple-tab-span">	</span></p>
<p class="p6"><span class="Apple-tab-span">	</span><span class="s1">Out</span>.ar(0,[<span class="s1">SinOsc</span>.ar(freq,0.1),in]);</p>
<p class="p6">}).play(s);</p>
<p class="p6">)</p>
<p class="p10"><br></p>
<p class="p10"><br></p>
<p class="p4"><br></p>
</body>
</html>
